package org.jugile.util;

import java.util.ArrayList;
import java.util.List;

/*

Copyright (C) 2007-2011 Jukka Rahkonen  email: jukka.rahkonen@iki.fi

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*/

/**
 * "All things were made by him; and without him was not any thing made that was made.
 *  In him was life; and the life was the light of men. And the light shineth in darkness; 
 *  and the darkness comprehended it not." (John 1:3-5)
 * 
 * ===========
 * 
 * Buffer is a more convinient version of StringBuffer for constructing indented 
 * string blocks inside code loops. Short method names for adding lines and null checked
 * char and String additions.
 * 
 * @author jukka.rahkonen@iki.fi
 */
public class Buffer extends Jugile {

	private StringBuffer buf;
	private String incrementStr = "    ";
	private boolean linemode = false;
	private List<String> items = new ArrayList<String>();
	private String listSeparator = null;
	
	public Buffer() { 
		buf = new StringBuffer();	
	}
	public Buffer(String incr) {
		buf = new StringBuffer(); 
		incrementStr = incr;
	}

	// no new lines and no indents
	public void setLinemode(boolean v) { linemode = v; }
	
	public String toString() { 
		checkList();
		if (!linemode) return buf.toString();
		return buf.toString().replaceAll("\n", " ");
	}
	
	public Buffer nl() { return add("\n"); }
	public Buffer ln() { return ln("");	}
	public Buffer ln(String line) {
		checkList();
		_ln(line);
		return this;
	}
	
	public Buffer add(String str) {
		checkList();
		_add(str);
		return this;
	}
	public Buffer add(char ch) {
		checkList();
		_add(ch);
		return this;
	}

	private void _add(String str) {
		if (str == null) str = "";
		buf.append(str);
	}
	private void _add(char ch) {
		if (ch > 0) buf.append(ch);
	}
	private void _nl() {
		_add("\n");
	}
	private void _ln() { _ln(""); }
	private void _ln(String line) { 
		_add(getIndent());
		_add(line);
		_nl(); 
	}
	
	public void list(String item) { list(item,","); }
	public void list(String item, String separator) {
		listSeparator = separator;
		item(item);
	}
	private void checkList() {
		if (items.size() > 0) join(listSeparator);
	}
	
	public void item(String str) {
		items.add(str);
	}
	public void join(String ch) {
		if (items.size() > 0) {
			_add(join(items, ch));
			items = new ArrayList<String>();
		}
	}
	public void joinAsLines(String ch) {
		if (items.size() > 0) {
			for (int i = 0; i < items.size(); i++) {
				_nl();
				_ind();
				_add(items.get(i));
				if (i < items.size()-1) {
					_add(ch);
				}
			}
			_nl();
			items = new ArrayList<String>();
		}
	}
	
	public String flush() {
		String s = toString();
		buf = new StringBuffer();
		return s;
	}
	public String flush(char ch) {
		add(ch);
		return flush();
	}
	
	public int size() {
		checkList();
		return buf.length();
	}

	private int indent = 0;
	public void incrIndent() { indent++; }
	public void decrIndent() { if (indent > 0) indent--; }
	public String getIndent() {
		if (linemode) return "";
		return mult(incrementStr, indent); 
	}
	public void resetIndent() { indent = 0; }
	public Buffer ind() { _ind(); return this; }
	private void _ind() { _add(getIndent()); }
	public int getIndentCount() { return indent; }
	
	public void insertBeforeLastNewLine(String str) {
		int idx = buf.lastIndexOf("\n");
		buf.insert(idx, str);
	}

	public void insert(String str) {
		buf.insert(0,str);
	}
	public void print() {
		print(this.toString());
	}
	
	public void delete(int count) {
		buf.delete(buf.length()-count, buf.length());
	}
	
}
